package com.witmore.neutron.ai.cognitive.service;

import com.witmore.neutron.ai.cognitive.dto.SessionDeductionRequest;
import com.witmore.neutron.ai.cognitive.exception.SessionUsageException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户会话次数扣减服务
 * Author: 豆子高
 * Date: 2025/1/15
 */
@Slf4j
@Service
public class UserSessionUsageService {


    @Autowired
    private SessionUsageLockStrategy lockStrategy;

    @Autowired
    private UserSessionUsageManager userSessionUsageManager;

    /**
     * 扣减用户会话次数（原子操作：检查+扣减在同一个锁内）
     *
     * @param request 扣减请求参数
     * @throws SessionUsageException 当用户不存在、余额不足或扣减失败时抛出
     */
    public void deductUserSessionCount(SessionDeductionRequest request) {
        try {
            // 使用智能锁策略，在同一个锁内完成检查+扣减的原子操作
            lockStrategy.executeWithSmartLock("deduct", request.getUserId(), request.getSessionId(), () -> {
                userSessionUsageManager.doDeductUserSessionCountAtomic(request);
                return null;
            });
        } catch (SessionUsageException e) {
            // 重新抛出业务异常
            throw e;
        } catch (Exception e) {
            log.error("扣减用户会话次数时获取锁失败，userId: {}, modelId: {}, sessionId: {}",
                    request.getUserId(), request.getModelConfigDO().getId(), request.getSessionId(), e);
            throw new SessionUsageException.DeductionFailedException(request.getUserId(), 0, e);
        }
    }


    /**
     * 检查用户会话次数
     *
     * @param request 请求参数
     */
    public boolean checkUserSessionCount(SessionDeductionRequest request) {
        try {

            // 使用智能锁策略，在同一个锁内完成检查+扣减的原子操作
            return lockStrategy.executeWithSmartLock("check", request.getUserId(), request.getSessionId(), () -> {
                return userSessionUsageManager.checkUserSessionCount(request.getUserId(), request.getModelConfigDO().getSessionCostCount());
            });
        } catch (SessionUsageException e) {
            // 重新抛出业务异常
            throw e;
        } catch (Exception e) {
            log.error("扣减用户会话次数时获取锁失败，userId: {}, modelId: {}, sessionId: {}",
                    request.getUserId(), request.getModelConfigDO().getId(), request.getSessionId(), e);
            throw new SessionUsageException.DeductionFailedException(request.getUserId(), 0, e);
        }
    }


}
